#! /bin/sh -p
#
# Run rtems tests on the Motorola MCF5206eLITE Coldfire Evaluation board
# using gdb configured with P&E Micro Background Debug Mode debugging
# interface.
#
# This program generates a gdb script to run each test, intercept
# serial port output and put log into output file.
#
# Author: Victor V. Vengerov <vvv@oktet.ru>
# Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia
#
# Partially based on runtest script for powerpc psim.
#
#  COPYRIGHT (c) 1989-1999.
#  On-Line Applications Research Corporation (OAR).
#
#  The license and distribution terms for this file may be
#  found in the file LICENSE in this distribution or at
#  http://www.rtems.org/license/LICENSE.
#

# progname=`basename $0`
progname=${0##*/}        # fast basename hack for ksh, bash

USAGE=\
"usage: $progname [ -opts ] test [ test ... ]
	-s ttydevice -- specify serial device to be used to capture test
                        output
        -r baud      -- set serial port baud rate (19200 by default)
        -b bdmdevice -- specify BDM device to be used to control the target
        -g gdbname   -- specify name of gdb program to be used
        -v           -- verbose output
        -d           -- don't remove temporary files (for debugging only)
        -i           -- use interrupt driven console I/O when test is running
                        (many tests failed when interrupt driven console
                        input/output is used due undetermenistic tests
                        behaviour)
        -p           -- use termios poll console I/O
        -l logdir    -- specify log directory (default is 'logdir')

  Specify test as 'test' or 'test.exe'.
  All multiprocessing tests *must* be specified simply as 'mp01', etc.
"

# export everything
set -a

#   log an error to stderr
prerr()
{
    echo "$*" >&2
}

fatal() {
    [ "$1" ] && prerr $*
    prerr "$USAGE"
    exit 1
}

warn() {
    [ "$1" ] && prerr $*
}

# run at normal and signalled exit
test_exit()
{
    exit_code=$1

    rm -f ${logfile}.tmp*
    [ "$gdb_pid" ] && kill -9 $gdb_pid
    [ "$serial_pid" ] && kill -9 $serial_pid

    exit $exit_code
}

#
# process the options
#
# defaults for getopt vars
#
# max_run_time is defaulted to 5 minutes
#

verbose=""
serial_device=/dev/ttyS0
bdm_device=/dev/bdmcf0
gdbprog=true
for i in rtems bdm-rtems bdm bdm-elf bdm-coff ; do
    if m68k-$i-gdb --version > /dev/null 2>&1 ; then
        gdbprog=m68k-$i-gdb ;
        break ;
    fi
done
logdir=log
max_run_time=$((5 * 60))
sizeof_ram=$((1 * 1024 * 1024))
debugging="no"
baudrate="19200"
console_mode=0

while getopts vdips:r:b:l: OPT
do
    case "$OPT" in
	v)
	    verbose="yes";;
        d)
            debugging="yes";;
        s)
            serial_device="$OPTARG";;
        r)
            baudrate="$OPTARG";;
        b)
            bdm_device="$OPTARG";;
        l)
            logdir="$OPTARG";;
        s)
            gdbprog="$OPTARG";;
        p)
            console_mode=1;;
        i)
            console_mode=2;;
        *)
            fatal;;
    esac
done

let $((shiftcount = $OPTIND - 1))
shift $shiftcount

args=$*

#
# Run the tests
#

tests="$args"
if [ ! "$tests" ]
then
     set -- `echo *.exe`
     tests="$*"
fi

[ -d $logdir ] ||
  mkdir $logdir || fatal "could not create log directory ($logdir)"

# where the tmp files go
trap "test_exit" 1 2 3 13 14 15

for tfile in $tests
do

   tname=`basename $tfile .exe`
   cpus="1"
   TEST_TYPE="single"

   case "$tname" in
       # size is no longer interactive.
       capture* | monitor* | termios* | fileio* | pppd*)
            warn "Skipping $tname; it is interactive"
            continue
            ;;
       *-node2*)
           warn "Skipping $tname; 'runtest' runs both nodes when for *-node1"
           continue
           ;;
       *-node1*)
           warn "Running both nodes associated with $tname"
           tname=`echo $tname | sed 's/-node.*//'`
           TEST_TYPE="mp"
           ;;
       minimum*|stackchk*|*fatal*|malloctest*)
           continue
           ;;
   esac

   if [ "$TEST_TYPE" = "mp" ] ; then
       fatal "MP tests not supported for this board"
   fi

   if [ $TEST_TYPE = "single" ] ; then
     logfile=$logdir/${tname}
     infofile=${logfile}.info
     scriptfile=${logfile}.ss
     gdblogfile=${logfile}.gdb

     rm -f ${logfile}.tmp*

     date=`date`
     echo "Starting $tname at $date"

     # Set serial port parameters
     if ! stty -F ${serial_device} raw cs8 -cstopb cread crtscts \
                    ispeed ${baudrate} ospeed ${baudrate} \
                    > /dev/null 2> /dev/null ; then
         fatal "Serial port couldn't be configured"
     fi

     # Flush serial port
     cat ${serial_device} > /dev/null &
     serial_pid=$!
     sleep 1s
     kill ${serial_pid}

     # Capture serial port
     cat ${serial_device} > $logfile &
     serial_pid=$!

     cat > "${scriptfile}" <<EOF
target bdm $bdm_device
set \$mbar  = 0x10000001
set \$csar0 = \$mbar - 1 + 0x064
set \$csmr0 = \$mbar - 1 + 0x068
set \$cscr0 = \$mbar - 1 + 0x06E
set \$csar1 = \$mbar - 1 + 0x070
set \$csmr1 = \$mbar - 1 + 0x074
set \$cscr1 = \$mbar - 1 + 0x07A
set \$csar2 = \$mbar - 1 + 0x07C
set \$csmr2 = \$mbar - 1 + 0x080
set \$cscr2 = \$mbar - 1 + 0x086
set \$csar3 = \$mbar - 1 + 0x088
set \$csmr3 = \$mbar - 1 + 0x08C
set \$cscr3 = \$mbar - 1 + 0x092
set \$csar4 = \$mbar - 1 + 0x094
set \$csmr4 = \$mbar - 1 + 0x098
set \$cscr4 = \$mbar - 1 + 0x09E
set \$csar5 = \$mbar - 1 + 0x0A0
set \$csmr5 = \$mbar - 1 + 0x0A4
set \$cscr5 = \$mbar - 1 + 0x0AA
set \$csar6 = \$mbar - 1 + 0x0AC
set \$csmr6 = \$mbar - 1 + 0x0B0
set \$cscr6 = \$mbar - 1 + 0x0B6
set \$csar7 = \$mbar - 1 + 0x0B8
set \$csmr7 = \$mbar - 1 + 0x0BC
set \$cscr7 = \$mbar - 1 + 0x0C2
#  
set *((short*) \$csar0) = 0xffe0
set *((int*)   \$csmr0) = 0x000f0000
set *((short*) \$cscr0) = 0x1da3
set *((short*) \$csar1) = 0x5000
set *((int*)   \$csmr1) = 0x00000000
set *((short*) \$cscr1) = 0x3d43
set *((short*) \$csar2) = 0x3000
set *((int*)   \$csmr2) = 0x000f0000
set *((short*) \$cscr2) = 0x1903
set *((short*) \$csar3) = 0x4000
set *((int*)   \$csmr3) = 0x000f0000
set *((short*) \$cscr3) = 0x0083
#
load
# Many tests not working properly when interrupt driven console I/O is used.
set console_mode=$console_mode
set \$pc=start
set \$sp=0x20001ffc
#
break bsp_cleanup
commands
shell kill $serial_pid
quit
end
#
break _stop
commands
shell kill $serial_pid
quit 1
end
#
continue
quit 2
EOF
     ${gdbprog} -x "${scriptfile}" "${tfile}" > "${gdblogfile}"  2>&1 &
     gdb_pid=$!
     {
         time_run=0
         while [ $time_run -lt $max_run_time ] ; do
             sleep 10s
             if kill -0 $gdb_pid 2> /dev/null ; then
                 time_run=$((time_run+10)) ;
             else
                 exit 0
             fi
         done
         kill -2 $serial_pid 2> /dev/null
         kill -2 $gdb_pid 2> /dev/null
         {
             sleep 5s ; 
             if kill -0 $gdb_pid 2> /dev/null ; then
                 kill -9 $gdb_pid 2> /dev/null ;
             fi
             if kill -0 $serial_pid 2> /dev/null ; then
                 kill -9 $serial_pid 2> /dev/null ;
             fi
         } &
     } &
     wait $gdb_pid
     gdb_status=$?
     {
         if kill -0 $serial_pid 2> /dev/null ; then
             kill $serial_pid 2> /dev/null ;
         fi
         sleep 5s ;
         if kill -0 $serial_pid 2> /dev/null ; then
             kill -9 $serial_pid 2> /dev/null ;
         fi
     } &
     if [ $gdb_status -ge 128 ] ; then
         ran_too_long="yes" ;
     else
         ran_too_long="no"
     fi
     if [ $gdb_status -ne 0 ] ; then
         test_failed="yes" ;
     else
         test_failed="no"
     fi
     gdb_pid=""
     serial_pid=""
   fi

   # Create the info files
   {
       echo "$date"
       echo "Test run on: `uname -n`"
       echo "Host Information:"
       echo `uname -a`
       echo
       echo "Serial port: ${serial_device}"
       echo "Baud rate:   ${baudrate}"
       echo "BDM port:    ${bdm_device}"
       echo "gdb:         `type -path ${gdbprog}`"

       cat ${logfile}

       if [ "$test_failed" = "yes" ] ; then
           echo -e "\\n\\nTest did not finish normally"
           if [ "$ran_too_long" = "yes" ] ; then
               echo "Test killed after $max_run_time seconds"
           fi
       fi

       echo
       date;
   } > ${infofile}
   if [ "${debugging}" = "no" ] ; then
       rm -f ${scriptfile}
       rm -f ${gdblogfile}
   fi
done

echo "Tests completed at " `date`
test_exit 0
